/*
 * SPDX-License-Identifier: BSD-3-Clause
 *
 */
#include "InfoNES_System.h"
#include "InfoNES.h"
#include <string.h>
#include "hpm_nes_port.h"

WORD NesPalette[64]={
    0x73AE, 0x20D1, 0x0015, 0x4013, 0x880E, 0xA802, 0xA000, 0x7840,
    0x4160, 0x0220, 0x0280, 0x01E2, 0x19EB, 0x0000,0x0000, 0x0000,
    0xBDF7, 0x039D, 0x21DD, 0x801E, 0xB817, 0xE00B, 0xD940, 0xCA61,
    0x8B80, 0x04A0, 0x0540, 0x0487,0x0411, 0x0000, 0x0000, 0x0000,
    0xF79E, 0x3DFF, 0x5CBF, 0xA45F, 0xF3DF, 0xFBB6, 0xFBAC, 0xFCC7,
    0xF5E7, 0x8682,0x4EE9, 0x5FD3, 0x075B, 0x73AE, 0x0000, 0x0000,
    0xFFFF, 0xAF3F, 0xC6BF, 0xD65F, 0xFE3F, 0xFE3B, 0xFDF6, 0xFED5,
    0xFF34, 0xE7F4, 0xAF97, 0xB7F9, 0x9FFE, 0xBDF7,0x0000,0x0000
};

/* Menu screen */
int InfoNES_Menu()
{
    return 0;
}


extern const BYTE nes_rom[];
/* Read ROM image file */
int InfoNES_ReadRom( const char *pszFileName )
{
/*
 *  Read ROM image file
 *
 *  Parameters
 *    const char *pszFileName          (Read)
 *
 *  Return values
 *     0 : Normally
 *    -1 : Error
 */


  /* Read ROM Header */
  BYTE * rom = (BYTE*)nes_rom;
  memcpy( &NesHeader, rom, sizeof(NesHeader));
  if ( memcmp( NesHeader.byID, "NES\x1a", 4 ) != 0 )
  {
    /* not .nes file */
    return -1;
  }
  rom += sizeof(NesHeader);

  /* Clear SRAM */
  memset( SRAM, 0, SRAM_SIZE );

  /* If trainer presents Read Triner at 0x7000-0x71ff */
  if ( NesHeader.byInfo1 & 4 )
  {
    //memcpy( &SRAM[ 0x1000 ], rom, 512);
	rom += 512;
  }

  /* Allocate Memory for ROM Image */
  ROM = rom;
  rom += NesHeader.byRomSize * 0x4000;

  if ( NesHeader.byVRomSize > 0 )
  {
    /* Allocate Memory for VROM Image */
	VROM = (BYTE*)rom;
	rom += NesHeader.byVRomSize * 0x2000;
  }

  /* Successful */
  return 0;
}


/* Release a memory for ROM */
void InfoNES_ReleaseRom()
{
}


/* Transfer the contents of work frame on the screen */
void InfoNES_LoadFrame(void)
{
    area_t area = {NES_DISP_HEIGHT, NES_DISP_WIDTH};
    hpm_display_flush(&area, WorkFrame);
}

/* Get a joypad state */
void InfoNES_PadState( DWORD *pdwPad1, DWORD *pdwPad2, DWORD *pdwSystem )
{
    uint32_t key_input = hpm_key_read();

    *pdwPad1 = key_input;
}


/* memcpy */
void *InfoNES_MemoryCopy( void *dest, const void *src, int count )
{
    return memcpy(dest,src,count);
}


/* memset */
void *InfoNES_MemorySet( void *dest, int c, int count )
{
    return memset(dest,c,count);
}


/* Print debug message */
void InfoNES_DebugPrint( char *pszMsg )
{
}


/* Wait */
void InfoNES_Wait()
{
    hpm_key_scan();
}


/* Sound Initialize */
void InfoNES_SoundInit( void )
{
}


/* Sound Open */
int InfoNES_SoundOpen( int samples_per_sync, int sample_rate )
{
    return 0;
}


/* Sound Close */
void InfoNES_SoundClose( void )
{
}


extern audio_elem_t wave_buf[735 * 3];
/* Sound Output 5 Waves - 2 Pulse, 1 Triangle, 1 Noise, 1 DPCM */
void InfoNES_SoundOutput(int samples, BYTE *wave1, BYTE *wave2, BYTE *wave3, BYTE *wave4, BYTE *wave5)
{
    for (uint32_t i=0; i<735; i++) {
        uint32_t data = (wave1[i] + wave2[i] + wave3[i] + wave4[i] + wave5[i]);
        for(uint32_t j=0; j<3; j++) {
            wave_buf[3*i + j].elem = data << 20;
        }
    }
    hpm_audio_play();
}


/* Print system message */
void InfoNES_MessageBox( char *pszMsg, ... )
{
}
